<?php

/**
 * This is the model class for table "users".
 *
 * The followings are the available columns in table 'users':
 * @property integer $user_id
 * @property string $username
 * @property string $email
 * @property string $password
 * @property string $salt
 * @property string $display_name
 * @property string $activation_key
 * @property string $type
 * @property integer $status
 * @property integer $joined
 * @property string $first_name
 * @property string $last_name
 * @property string $gender
 * @property string $social_provider
 * @property string $social_uid
 * @property string $access_token
 * @property string $bio
 * @property integer $last_login_time
 * @property string $last_login_ip
 * @property string $country
 * @property string $state
 * @property string $city
 * @property string $address
 * @property string $phone
 * @property string $telephone
 * @property string $mobile
 * @property string $postcode
 * @property integer $featured
 * @property string $avatar
 * @property string $webpage
 * @property string $timezone
 * @property string $language
 *
 * The followings are the available model relations:
 * @property Posts[] $posts
 */
class User extends CActiveRecord {
    /**
     * hold the password after find
     * @var string
     */
    public $initialPassword;
    /**
     * password required when change or create new
     * @var string
     */
    public $repassword;

    const STATUS_WAITING_ACTIVE = 0;
    const STATUS_ACTIVE = 1;
    const STATUS_SUSPENDED = 2;

    const GENDER_FEMALE = 'female';
    const GENDER_MALE = 'male';

    /**
     * define user type
     */
    const TYPE_SUPER_ADMIN = 'supperAdmin';
    const TYPE_ADMIN = 'admin';
    const TYPE_MEMBER = 'member';

    /**
 * Returns the static model of the specified AR class.
 * @param string $className active record class name.
 * @return User the static model class
 */
    public static function model($className = __CLASS__) {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName() {
        return '{{users}}';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules() {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('email', 'required'),
            array('password, repassword', 'required', 'on' => 'insert'),
            array('username, email', 'unique'),
            array('email', 'email'),
            array('gender', 'in', 'range' => array(self::GENDER_FEMALE, self::GENDER_MALE)),
            array('user_id, status, joined, last_login_time, featured', 'numerical', 'integerOnly' => true),
            array('email, password, salt, display_name, activation_key', 'length', 'max' => 128),
            array('type, first_name, last_name, social_provider, last_login_ip, username', 'length', 'max' => 25),
            array('gender', 'length', 'max' => 6),
            array('social_uid, access_token, address, avatar, webpage', 'length', 'max' => 255),
            array('country, state, city, telephone, mobile, timezone', 'length', 'max' => 45),
            array('phone, postcode', 'length', 'max' => 15),
            array('language', 'length', 'max' => 10),
            array('bio', 'safe'),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('user_id, email, password, salt, display_name, type, status, joined, first_name, last_name, gender, social_provider, social_uid, access_token, bio, country, state, city, address, phone, telephone, mobile, postcode, webpage, language', 'safe', 'on' => 'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations() {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'posts' => array(self::HAS_MANY, 'Posts', 'author_id'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels() {
        return array(
            'user_id' => 'ID',
            'username' => 'Username',
            'email' => 'Email',
            'password' => 'Password',
            'salt' => 'Salt',
            'display_name' => 'Display Name',
            'activation_key' => 'Activation Key',
            'type' => 'Type',
            'status' => 'Status',
            'joined' => 'Joined',
            'first_name' => 'First Name',
            'last_name' => 'Last Name',
            'gender' => 'Gender',
            'social_provider' => 'Social Provider',
            'social_uid' => 'Social Uid',
            'access_token' => 'Access Token',
            'bio' => 'Bio',
            'last_login_time' => 'Last Login Time',
            'last_login_ip' => 'Last Login Ip',
            'country' => 'Country',
            'state' => 'State',
            'city' => 'City',
            'address' => 'Address',
            'phone' => 'Phone',
            'telephone' => 'Telephone',
            'mobile' => 'Mobile',
            'postcode' => 'Postcode',
            'featured' => 'Featured',
            'avatar' => 'Avatar',
            'webpage' => 'Webpage',
            'timezone' => 'Timezone',
            'language' => 'Language',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search() {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria = new CDbCriteria;

        $criteria->compare('user_id', $this->user_id);
        $criteria->compare('email', $this->email, true);
        $criteria->compare('display_name', $this->display_name, true);
        $criteria->compare('activation_key', $this->activation_key, true);
        $criteria->compare('type', $this->type, true);
        $criteria->compare('status', $this->status);
        $criteria->compare('joined', $this->joined);
        $criteria->compare('first_name', $this->first_name, true);
        $criteria->compare('last_name', $this->last_name, true);
        $criteria->compare('gender', $this->gender, true);
        $criteria->compare('social_provider', $this->social_provider, true);
        $criteria->compare('social_uid', $this->social_uid, true);
        $criteria->compare('bio', $this->bio, true);
        $criteria->compare('country', $this->country, true);
        $criteria->compare('state', $this->state, true);
        $criteria->compare('city', $this->city, true);
        $criteria->compare('address', $this->address, true);
        $criteria->compare('phone', $this->phone, true);
        $criteria->compare('telephone', $this->telephone, true);
        $criteria->compare('mobile', $this->mobile, true);
        $criteria->compare('postcode', $this->postcode, true);
        $criteria->compare('featured', $this->featured);
        $criteria->compare('webpage', $this->webpage, true);
        $criteria->compare('language', $this->language, true);

        //order
        $criteria->order = 'joined DESC';

        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
            'pagination' => array(
                'pageSize' => param('pageSize')
            )
        ));
    }

    /**
     * before save check is new user then update user register date
     * @return boolean
     */
    public function beforeSave() {
        if (parent::beforeSave()) {
            if ($this->isNewRecord) {
                $this->registered = time();

                //check
                if ($this->scenario == 'insert') {
                    //create random salt
                    $this->salt = $this->__generateSalt();
                }
            } else {

            }

            // in this case, we will use the old hashed password.
            if (empty($this->password) && empty($this->repassword) && !empty($this->initialPassword))
                $this->password = $this->repassword = $this->initialPassword;
            else
                $this->password = $this->hashPassword($this->password, $this->user_salt);

            return TRUE;
        }
        return FALSE;
    }

    /**
     * action after find result
     */
    public function afterFind() {
        //reset the password to null because we don't want the hash to be shown.
        $this->initialPassword = $this->password;
        $this->password = null;

        parent::afterFind();
    }

    /**
     * Checks if the given password is correct.
     * @param string the password to be validated
     * @return boolean whether the password is valid
     */
    public function validatePassword($password) {
        return $this->hashPassword($password, $this->salt) === $this->initialPassword;
    }

    /**
     * Generates the password hash.
     * @param string password
     * @param string salt
     * @return string hash
     */
    public function hashPassword($password, $salt) {
        return md5($salt . $password);
    }

    /**
     * Generates a salt that can be used to generate a password hash.
     * @return string the salt
     */
    protected function __generateSalt() {
        return uniqid('', true);
    }


    /**
     * get text of status
     * @return string
     */
    public function getStatusText(){
        switch($this->status){
            case self::STATUS_ACTIVE :
                $return = 'Actived';
                break;
            case self::STATUS_SUSPENDED :
                $return = 'Suspended';
                break;
            case self::STATUS_WAITING_ACTIVE :
                $return = 'Waiting to active';
                break;
            default :
                $return = 'Undefined';
                break;
        }

        return $return;
    }

    /**
     * get range status allow
     * @return array $status_key => $text
     */
    public static function getStatusRange(){
        return array(
            self::STATUS_WAITING_ACTIVE => 'Waiting Active',
            self::STATUS_ACTIVE => 'Active',
            self::STATUS_SUSPENDED => 'Suspended'
        );
    }


    /**
     * get type of current user
     */
    public function getType(){

    }

    /**
     * get avatar url of current user
     * allow size: small, thumb, medium, large, full
     * if user is logon with social provider, return url of social provider
     * @param string $size small, thumbnail, medium, large, full
     */
    public function getAvatarUrl($size = 'thumb'){
        switch($size){
            case 'thumb' :
                $width = 200; $height = 150;
                break;
            case 'small' :
                $width = 64; $height = 64;
                break;
            default :
                $width = 800; $height = 600;
                break;
        }

        if($this->avatar == '' && $this->social_provider == ''){
            //empty
            $avatar = 'default.png';
        }else{
            $avatar = $this->avatar;
        }

        return ImageHelper::thumb($width, $height, 'avatar'.DIRECTORY_SEPARATOR.$avatar);
    }

    /**
     * get range of gender
     * @return array key => value
     */
    public static function getGenderRange(){
        return array(
            self::GENDER_FEMALE => 'Female',
            self::GENDER_MALE => 'Male'
        );
    }

    /**
     *
     * @return type
     */
    public static function getTypeRange(){
        return array(
            self::TYPE_MEMBER => 'Member',
            self::TYPE_ADMIN => 'Admin',
            self::TYPE_SUPER_ADMIN => 'Super Admin'
        );
    }
}